<?php
class CategoryModel {
	
	/**
	 * 循环将分类分组逻辑处理,生成得到对应的级别关系
	 * @param int $id id
	 * @param array $arr 整个分类数组
	 * @param int $param.level 取$level个子级
	 * @param int $param.getOnlyOneLevel (此参有值时代表$level参数失效)仅获取第$getOnlyOneLevel级的数据
	 * @param boolean $param.hasParent 是否包含顶级父分类(默认为false)
	 * @return array 梳理过层级关系的二维数组
	 */
	function getCat($id,$arr,$param=''){
			if(!function_exists('tree2list')){ //在这个框架里面 由于模型层的问题 所以只能做这样的判断
				function tree2list($listTree,$class=1,$level=0){//class为当前循环的分类级别
					if(!is_array($listTree)) return array();
					foreach ($listTree as $row){
						//判断取分类级别限制
						if($class<=$level OR $level==0){
							$row['level'] = $class;
							$list[$row['id']] = $row;
							if(isset($row['_child'])){
								$subClass = $class;$subClass++;//每进一个子级则层级+1
								$child_arr = tree2list($row['_child'],$subClass,$level);
								if(is_array($child_arr))
								foreach ($child_arr as $arr){
									$list[$arr['id']] = $arr;
								}
								unset($list[$row['id']]['_child']);
							}
						}
					}
					return isset($list)?$list:'';	
				}
			}

		if(!is_array($arr)) return false;//非数组,返回
		//数据初始化
		$id=(int)$id;
		$level = My::arr2var($param,'level',0);
		$getOnlyOneLevel = My::arr2var($param,'getOnlyOneLevel',0);
		$hasParent = My::arr2var($param,'hasParent',false);
		//生成树结构
		$result = list_to_tree($arr,'id','parent_id','_child',$id);
		//顶级父分类
		if(isset($result[$id]))
			$parent = $result[$id];
		$result = tree2list($result, 1, ($getOnlyOneLevel>0)?$getOnlyOneLevel:$level);//生成带层级关系数值的二维数组
		$result = (isset($parent) AND is_array($parent) AND is_array($result))?array_merge($parent,$result):$result;//将顶级父分类合并进来
		//仅获取第$getOnlyOneLevel级的数据(删除$leve不等于$getOnlyOneLevel的分类)
		if($getOnlyOneLevel>0 AND is_array($result)){
			foreach($result as $key=>$value) if($value['level']!=$getOnlyOneLevel) unset($result[$key]);
		}
		$result = is_array($result)?array_values($result):array();//键值重排(以0++为键值)
		//是否包含父分类
		if($hasParent==true){
			$parent[$id] = DB('category')->where("id={$id}")->cache()->find();
			if(is_array($parent[$id]))
				$parent[$id]['level'] = 0;
			//如果parent顶级分类有值,则合并到result中
			if(is_array($parent[$id]) AND is_array($result)){
				$result = array_merge($parent,$result);//将父分类合并到数组头部
			}elseif(is_array($parent[$id]) AND !is_array($result)){
				$result = $parent;
			}else{
				$result = '';
			}
		}
		//解释params & 重置key值为数据id
		$returnData = '';
		if(is_array($result))
		foreach($result as &$value){
			$value['params'] = My::decodeJson($value['params']);
			$returnData[$value['id']] = $value;
		}
		//return
		return $returnData;
	}

	/**
	 * 分类ID -> 下拉搜索所需要的数组
	 * @param int $id 分类ID
	 * @param int $param.level 取子分类级数
	 * @param boolean $param.hasParent 是否包含父分类(默认false)
	 * 注意注意:::这里返回的数据有两种,一种是数组$result['data'],另外一种才是select下拉数据:$result['select']
	 * @return array
	 */
	public function id2select($id=0,$param=''){
		//init $param
		$level = isset($param['level'])?(int)$param['level']:0;
		$hasParent = (isset($param['hasParent']) AND $param['hasParent']==true)?true:false;
		//得到当前参数的分类详细信息
		$me = My::id2detail('category',$id);
		//通过当前分类,得到顶级父分类一唯数组
		$parent[] = self::id2topParent($me['id']);
		//父分类的标题处理(左右加上字符串)
		if(is_array($parent[0]))
			$parent[0]['title'] = '--【'.$parent[0]['title'].'】--';
		//根据父分类item名称,得到表单模型分类(用于下拉搜索)
		$data = self::id2submenu(isset($parent[0]['id'])?$parent[0]['id']:0,array('level'=>$level,'hasParent'=>true));
		//是否合并父分类
		if($hasParent AND is_array($data) AND is_array($parent)) $data = array_merge($parent,$data);
		//当$data无数据时,取parent值
		if(!$data AND is_array($parent)) $data = $parent;
		$result['data'] = $data;
		//print_r($data);exit;
		//得到SELECT下拉框的option项
		if(is_array($data))
		foreach($data as $value){
			if(isset($value['level']) AND $value['level']>0)
				$titlePre = My::forecho($value['level'],'　').'|_';
			else
				$titlePre = '';
			$result['select'][$value['id']] = $titlePre.$value['title'];
		}
		//print_r($result);
		return $result;
	}
	/**
	 * 分类唯一名称 -> 下拉搜索所需要的数组
	 * @param string $item 分类名称
	 * @param 详细参数请参照function id2select()
	 * @return array
	 */
	public function item2select($item='',$param=''){
		if(!$item OR !My::is_var($item)) return false;
		$id = self::item2id($item);
		$result = '';
		if(My::is_id($id)) $result = self::id2select($id,$param);
		return $result;
	}

	/**
	 * 子分类ID -> 顶级父分类(一唯数组)
	 * @param int id 子分类ID
	 * @return array 顶级分类数
	 */
	public function id2topParent($id=0){
		$id = (int)$id;
		if(!$id) return -1;
		$temp_ = DB('category')->where("id={$id}")->cache()->getField('parent_id');
		$temp__ = 0;
		$parent_id = 0;
		$youLevel = 1;//记录当前$id分类所处的级别数
		while(true){
			if(My::is_id($temp_)) {
				$parent_id = $temp__;
				$temp__ = $temp_;
				$temp_ = DB('category')->where("id={$temp_}")->cache()->getField('parent_id');
				$youLevel++;//级别++
			}else{
				$parent_id = $temp__;
				break;
			}
		}
		$parent_id = My::is_id($parent_id)?$parent_id:$id;//父分类(非顶级分类)
		$result = My::id2detail('category',$parent_id);
		if($result<=0) return -2;
		$result['youLevel'] = $youLevel;
		return $result;
	}
	/**
	 * 子分类唯一名称 -> 顶级父分类(一唯数组)
	 * @param int item 子分类唯一名称
	 * @return array 顶级分类数组
	 */
	public function item2topParent($item=''){
		if(!$item OR !My::is_var($item)) return false;
		$id = self::item2id($item);
		$result = '';
		if(My::is_id($id)) $result = self::id2topParent($id);
		return $result;
	}

	/**
	 * 分类id -> 子菜单
	 * @param int $id 分类ID
	 * @param array $param.list 分类数组(有该值时不读取数据库,没有该数组时才从数据库中读取所有分类数据)
	 * @param int $param.level 指定获取一共几个级子分类,0代表不限制
	 * @param int $param.getOnlyOneLevel (可选参数,此参有值时代表$level参数失效)仅获取第$getOnlyOneLevel级的数据
	 * @param boolean $param.hasParent 是否包含顶级父分类(默认false)
	 * @param boolean $param.publish 是否包含未发布的数据(1:已发布,0:未发布,'all':全部,不传值时:默认1)
	 * @param string $param.where sql语句,用于读取category表数据<如“ AND publish=1”>(记得前面要有AND/OR/like...)
	 * @param string $param.is_tree 返回树结构数组(true/false默认false)
	 * @return array
	 */
	public function id2submenu($id=0,$param=''){
		//数据初始化
		$level = (int)My::arr2var($param,'level',0);
		$getOnlyOneLevel = (int)My::arr2var($param,'getOnlyOneLevel',0);
		$list = My::arr2var($param,'list');
		$hasParent = (My::arr2var($param,'hasParent')==true)?true:false;
		$where = (My::arr2var($param,'publish')=='1' OR My::arr2var($param,'publish')==='')?"publish=1 ":((My::arr2var($param,'publish')=='0')?'publish=0 ':'1');//publish->sql条件
		$where.= My::arr2var($param,'where',' AND 1 ');
		$id = (int)$id;
		if(!$id) return false;
		//判断是否存在缓存
		//echo serialize($param);exit;
		if(!$result=My::getCache($id.serialize($param),array('pre'=>'category'))){
		    //order排序
		    if(My::arr2var($param,'order')=='hot'){
		        $order = "hot DESC,ordering ASC,id DESC";
		    }else{
		        $order = "ordering ASC,id DESC";
		    }
			//全部子分类
			if(!is_array($list))
				$list = DB('category')->where($where)->order($order)->cache()->select();
			//当前主分类不存在$list数组中时,补充添加上去
			if(empty($list[$id])){
				$temp = DB('category')->where("id={$id}")->find();
				if($temp)
					$list[$id] = $temp;
			}
			//组合得到最终分类列表
			$result = self::getCat($id,$list,array('level'=>$level,'getOnlyOneLevel'=>$getOnlyOneLevel,'hasParent'=>$hasParent));
			//返回树结构数组
			if(My::arr2var($param,'is_tree')==true)
				$result = list_to_tree($result,'id','parent_id','_child',$id);
			//setCache
			My::setCache($id.serialize($param),$result,array('pre'=>'category'));
		}
		return $result;
	}
	/**
	 * 分类唯一名称 -> 子菜单
	 * @param 详细参数请参照function id2submenu()
	 * @return array
	 */
	public function item2submenu($item='',$param=''){
		if(!$item OR !My::is_var($item)) return false;
		$id = self::item2id($item);
		$result = '';
		if(My::is_id($id)) $result = self::id2submenu($id,$param);
		return $result;
	}

	/**
	 * 分类id -> 得到指定分类id下的所有第$level级分类($level=1表示取分类id下的一级分类)
	 * @param int $id 分类ID
	 * @param array $param.getOnlyOneLevel (可选参数,此参有值时代表$level参数失效)仅获取第$getOnlyOneLevel级的数据
	 * @param array $param.list 分类数组(有该值时不读取数据库,没有该数组时才从数据库中读取所有分类数据)
	 * @param boolean $param.hasParent 是否包含顶级父分类(默认false)
	 * @return array
	 */
	public function id2level($id=0,$param=''){
		//数据初始化
		$getOnlyOneLevel = isset($param['getOnlyOneLevel'])?$param['getOnlyOneLevel']:0;
		$list = isset($param['list'])?$param['list']:'';
		$hasParent = (isset($param['hasParent']) AND $param['hasParent']==true)?true:false;
		$id = (int)$id;

		$result = self::id2submenu($id,array('level'=>0,'list'=>$list,'getOnlyOneLevel'=>$getOnlyOneLevel,'hasParent'=>$hasParent));
		return $result;
	}
	/**
	 * 分类唯一名称 -> 得到指定分类id下的所有第$level级分类($level=1表示取分类id下的一级分类)
	 * @param int $item 分类唯一名称
	 * @param 详细参数请参照function id2level()
	 * @return array
	 */
	public function item2level($item='',$param=''){
		if(!$item OR !My::is_var($item)) return false;
		$id = self::item2id($item);
		$result = '';
		if(My::is_id($id)) $result = self::id2level($id,$param);
		return $result;
	}
	
	/**
	 * 分类id->分类的唯一名称
	 * @param int $id 分类ID
	 * @return string 分类的唯一名称
	 */
	public function id2item($id=0){
		$id = (int)$id;
		if(!$id) return false;
		return DB('category')->field('item')->where("id='$id'")->cache()->getField('item');
	}
	/**
	 * 分类唯一名称->分类id
	 * @param string $item 分类唯一名称
	 * @param string $param.publish 是否发布 1:已发布 0:未发布 其它任意值OR空:全部
	 * @return int 分类ID
	 */
	public function item2id($item='',$param=''){
		if(!$item OR !My::is_var($item)) return false;
		$where = (My::arr2var($param,'publish')=='1' OR My::arr2var($param,'publish')==='')?"publish=1 ":((My::arr2var($param,'publish')=='0')?'publish=0 ':'1');//publish->sql条件
		//exit($where);
		return DB('category')->where($where." AND item='$item'")->cache()->getField('id');
	}

	/**
	 * ids数组 -> 得到包括相应搜索结果的所有对应父分类列表
	 * @param array $ids IDS数组
	 * @return array 整个搜索结果数组
	 */
	public function ids2eachParent($ids){
		if(!is_array($ids)) return false;
		$id=0;$result='';
		foreach($ids as $value){
			$id = $value;
			if(!My::is_id($id)) continue;
			$result[$id] = My::id2detail('category',$id);
			$temp = 0;
			while(true){
				$parent_id = My::id2field('category',$id,'parent_id');
				if(My::is_id($parent_id)){
					$id = $parent_id;
					if(empty($result[$parent_id]))
						$result[$parent_id] = My::id2detail('category',$parent_id);
				}
				else break;
			}
		}
		//解释params参数
		if(isset($result) AND is_array($result))
		foreach($result as &$value){
			$value['params'] = My::decodeJson($value['params']);
		}
		$result = self::getCat($id,$result,array('hasParent'=>true));
		return $result;
	}

	/**
	 * 分类列表 后于后台设置:表单模型授权
	 */
	public function form_category_list(){
		$result = DB('category')->where("publish=1")->order('ordering ASC,id DESC')->cache()->select();
		$result = My::arr2one($result,array('id','title'));
		if(is_array($result))
		foreach($result as $key=>&$value){
			$value = "{$key} ".$value;
		}
		return $result;
	}
	
	
	/**
	 * 分类数组>转化为文字(逗号分隔)
	 * @param array $arr 分类数组(一维数组,value为分类id)
	 * @param string $sign 分隔符号
	 * @return string
	 */
	function catArr2text($arr='',$sign=','){
		if(empty($arr) OR !is_array($arr))
			return '';
		$result = array();
		foreach($arr as $value){
			$temp = My::id2field('category',$value,'title');
			if(!$temp OR $temp<0)
				continue;
			$result[$value] = $temp;
		}
		$result = implode($sign,$result);
		return $result;
	}
	
}